using System.Diagnostics;
using NUnit.Framework;
using Pinwheel.LSerialize;

namespace LSerialize.Test
{
    [LSerializable]
    public partial class TestBaseNode
    {
        public long guid;
    }
    
    [LSerializable]
    public partial class TestNodeA : TestBaseNode
    {
        public int A;
    }
    
    [LSerializable]
    public partial class TestNodeB : TestBaseNode
    {
        public int B;
    }
    
    [LSerializable]
    public partial class TestNodeC : TestNodeA
    {
        public TestBaseNode B;
        public int C;
    }
    
    [LSerializable]
    public partial class TestNodeD : TestBaseNode
    {
        public TestBaseNode C;
        public int D;
    }

    [LSerializable]
    public partial class TestGraph
    {
        public List<TestBaseNode> Nodes;
    }

    public unsafe class TestSerializeGraph
    {
        [Test]
        public void TestGraph()
        {
            var nodes = new List<TestBaseNode>(5);
            
            nodes.Add(new TestBaseNode()
            {
                guid = 0L
            });
            
            nodes.Add(new TestNodeA()
            {
                A = 1,
                guid = 1L
            });

            var b = new TestNodeB()
            {
                B = 2,
                guid = 2L
            };
            nodes.Add(b);

            var c = new TestNodeC()
            {
                B = b,
                C = 3,
                guid = 3L
            };
            nodes.Add(c);

            var d = new TestNodeD()
            {
                C = c,
                D = 4,
                guid = 4L
            };
            nodes.Add(d);
            
            // var dict = new Dictionary<int, TestBaseNode>();
            // dict.Add(1, b);
            // dict.Add(2, c);
            // dict.Add(3, d);

            byte[] buffer = null;
            
            TestGraph sTestGraph = new TestGraph();
            sTestGraph.Nodes = nodes;
            // buffer = LSerializer.Serialize<TestGraph>(ref testGraph, false);
            TestGraph tg = null;
            TestGraph dTestGraph = new TestGraph();
            
            buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, false);
            tg = LSerializer.Deserialize<TestGraph>(buffer, false);
            Assert.That(sTestGraph, Is.EqualTo(tg));
            
            // buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, false);
            // tg = LSerializer.Deserialize<TestGraph>(buffer, false);
            // // Assert.That(sTestGraph, Is.EqualTo(tg));
            //
            // buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, false);
            // tg = LSerializer.Deserialize<TestGraph>(buffer, false);
            // // Assert.That(sTestGraph, Is.EqualTo(tg));
            //
            // buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, false);
            // tg = LSerializer.Deserialize<TestGraph>(buffer, false);
            // // Assert.That(testGraph, Is.EqualTo(tg));
            //
            // buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, false);
            // tg = LSerializer.Deserialize<TestGraph>(buffer, false);
            // // Assert.That(testGraph, Is.EqualTo(tg));
            //
            // buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, true);
            // tg = LSerializer.Deserialize<TestGraph>(buffer, true);
            // // Assert.That(testGraph, Is.EqualTo(tg));
            
            buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, true);
            tg = LSerializer.Deserialize<TestGraph>(buffer, true);
            Assert.That(sTestGraph, Is.EqualTo(tg));
            
            // buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, true);
            // tg = LSerializer.Deserialize<TestGraph>(buffer, true);
            // // Assert.That(testGraph, Is.EqualTo(tg));
            //
            // buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, true);
            // tg = LSerializer.Deserialize<TestGraph>(buffer, true);
            // // Assert.That(testGraph, Is.EqualTo(tg));
            //
            // buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, true);
            // tg = LSerializer.Deserialize<TestGraph>(buffer, true);
            // // Assert.That(testGraph, Is.EqualTo(tg));
            //
            // buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, true);
            // tg = LSerializer.Deserialize<TestGraph>(buffer, true);
            // // Assert.That(testGraph, Is.EqualTo(tg));
            
            var watch = new Stopwatch();
            
            
            watch.Restart();
            for (int i = 0; i < 10000; i++)
            {
                buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, false);
            } 
            watch.Stop();
            dTestGraph = LSerializer.Deserialize<TestGraph>(buffer, false);
            Console.WriteLine($"LSerializer.Serialize Unpack1: {watch.ElapsedMilliseconds} ms, size: {buffer.Length}");
            
            // watch.Restart();
            // for (int i = 0; i < 10000; i++)
            // {
            //     buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, false);
            // } 
            // watch.Stop();
            // dTestGraph = LSerializer.Deserialize<TestGraph>(buffer, false);
            // Console.WriteLine($"LSerializer.Serialize Unpack2: {watch.ElapsedMilliseconds} ms, size: {buffer.Length}");
            //
            // watch.Restart();
            // for (int i = 0; i < 10000; i++)
            // {
            //     dTestGraph = LSerializer.Deserialize<TestGraph>(buffer, false);
            // }
            // watch.Stop();
            // Console.WriteLine($"LSerializer.Deserialize Unpack: {watch.ElapsedMilliseconds} ms, size: {buffer.Length}");
            //     
            // watch.Restart();
            // for (int i = 0; i < 10000; i++)
            // { 
            //     buffer = LSerializer.Serialize<TestGraph>(ref sTestGraph, true);
            // } 
            // watch.Stop();
            // Console.WriteLine($"LSerializer.Serialize Packed: {watch.ElapsedMilliseconds} ms, size: {buffer.Length}");
            //     
            // watch.Restart();
            // for (int i = 0; i < 10000; i++)
            // {
            //     dTestGraph = LSerializer.Deserialize<TestGraph>(buffer, true);
            // }
            // watch.Stop();
            // Console.WriteLine($"LSerializer.Deserialize Packed: {watch.ElapsedMilliseconds} ms, size: {buffer.Length}");
            //
            // var bytes = new byte[662];
            // int size = 0;
            // fixed (byte* ptr = &bytes[0])
            // {
            //     watch.Restart();
            //     for (int i = 0; i < 10000; i++)
            //     {
            //         size = LSerializer.FastSerialize<TestGraph>(ref sTestGraph, ptr, false);
            //     } 
            //     watch.Stop();
            //     Console.WriteLine($"LSerializer.FastSerialize Unpack3: {watch.ElapsedMilliseconds} ms, size: {size}"); 
            // }
            //
            // fixed (byte* ptr = &bytes[0])
            // {
            //     watch.Restart();
            //     for (int i = 0; i < 10000; i++)
            //     {
            //         size = LSerializer.FastSerialize<TestGraph>(ref sTestGraph, ptr, false);
            //     } 
            //     watch.Stop();
            //     Console.WriteLine($"LSerializer.FastSerialize Unpack4: {watch.ElapsedMilliseconds} ms, size: {size}"); 
            // }
            //
            // Console.WriteLine($"sTestGraph: {sTestGraph}, dTestGraph: {dTestGraph}");
        }
    } 
}

